﻿using System;

using OST.Shared;
using OST.Shared.Interfaces;
using OST.Shared.Extensions;
using OST.Persistence;
using OST.Motor;

using mfLogger;

namespace OST.Calc.Tracking
{
    /// <summary>
    /// provides a singlton-instance for interface-type <see cref="ITrackerProvider"/>
    /// </summary>
    public class TrackerProvider : ITrackerProvider
    {
        #region CTOR// Singleton
        //http://msdn.microsoft.com/en-us/library/ff650316.aspx
        //--> not thread-safe, with dynamic initialization

        private static TrackerProvider _instance = null;

        private TrackerProvider()
        {
            
        }

        public static TrackerProvider Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new TrackerProvider();
                }

                return _instance;
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// wrapper-property 4 logging
        /// </summary>
        private ILoggerAppender Logger
        {
            get
            {
                return mfLogger.mfLogger.Instance;
            }
        }

        #endregion

        #region ITrackerProvider
        public void Initialize()
        {
            MotorProvider.Instance.PropertyChanged += MotorProviderInstance_PropertyChanged;
            Logger.Debug("tracker-provider initiated");
        }

        void MotorProviderInstance_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // on motorprovider-instance-isInitialized @first time
            if (e.PropertyName == "HasInstance" && ((bool)e.PropertyNewValue)
                && TrackerInstance == null)
            {
                MotorProvider.Instance.MotorInstance.PropertyChanged += MotorInstance_PropertyChanged;
                Logger.Debug("tracker-provider: motor 'HasInstance' received");
            }
        }

        void MotorInstance_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // on motor-instance-isInitialized @first time
            if (e.PropertyName == "IsInitialized" && ((bool)e.PropertyNewValue)
                && TrackerInstance == null)
            {
                CreateTrackerInstance();
            }
        }

        private void CreateTrackerInstance()
        {
            if (!ConfigurationProvider.Instance.HasConfig)
            {
                Logger.Error("no config available for tracking, after motor initialization");
                return;
            }
            if (!MotorProvider.Instance.HasInstance)
            {
                Logger.Error("no motor available for tracker initialization");
                return;
            }

            TrackerInstance = new Tracker(MotorProvider.Instance.MotorInstance
                                        , ConfigurationProvider.Instance.ConfigInstance.Frame
                                        , ConfigurationProvider.Instance.ConfigInstance.Location);

            TrackerInstance.Start();

            OnNotifyPropertyChanged("HasInstance", true);
            Logger.Debug("tracker-provider initializde");
        }

        public ITracker TrackerInstance
        {
            get;
            private set;
        }

        public bool HasInstance
        {
            get { return TrackerInstance != null; }
        } 
        #endregion

        #region INotifyPropertyChanged

        /// <summary>
        /// notifies clients over changes in puplic properties
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnNotifyPropertyChanged(String propertyName, object newValue)
        {
            if (PropertyChanged != null && !propertyName.IsNullOrEmpty())
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName, newValue));
            }
        }

        #endregion
    }
}
